/*!
    \file    change log.txt
    \brief   change log for GD32A490 firmware

    \version 2026-02-05, V2.0.3, firmware for GD32A490
*/

/*
    Copyright (c) 2026, GigaDevice Semiconductor Inc.

    Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this 
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, 
       this list of conditions and the following disclaimer in the documentation 
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors 
       may be used to endorse or promote products derived from this software without 
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
*/
******************* V2.0.3 2026-02-05 ******************************************************************************************
______________________Common______________________________________________________________________________________________
1.add GD32EBuilder project, delete the print redirection function in main.c
2.Correct spelling errors
3.Fix MISRA-C 14.7 warning

/GD32A490_Firmware_Library/Firmware/CMSIS/GD/GD32A490/Include/gd32a490.h
fix reason: 
add hardfault irq
V2.0.2:
None
V2.0.3:
    HardFault_IRQn               = -13,    /*!< hard-fault interrupt                                     */

______________________________________________________________________________________________________________________

______________________TRNG________________________________________________________________________________________________
/GD32F4xx_Firmware_Library/GD32F4xx_Firmware_Library/Examples/TRNG/TRNG_poll_mode/gd32f4xx_it.c
/GD32F4xx_Firmware_Library/GD32F4xx_Firmware_Library/Examples/TRNG/TRNG_poll_mode/main.c
fix reason: 
add volatile key word in key var

V2.0.2:
NONE
V2.0.3:
volatile
__________________________________________________________________________________________________________________________

______________________ADC________________________________________________________________________________________________
Examples/ADC/ADC0_temperature_Vref_Vbat/main.c
Examples/ADC/ADC1_analog_watchdog/systick.c
Examples/ADC/ADC1_analog_watchdog/main.c	
Examples/ADC/ADC1_resolution_oversample/systick.c	
Examples/ADC/ADC1_resolution_oversample/main.c	

fix reason: 
Resolve the test failure under high optimization
V2.0.2:
None
V2.0.3:
__IO
__________________________________________________________________________________________________________________________

______________________IPA________________________________________________________________________________________________
/GD32F4xx_Firmware_Library/GD32F4xx_Firmware_Library/Examples/IPA/IPA_2images_blend/logo.h
/GD32F4xx_Firmware_Library/GD32F4xx_Firmware_Library/Examples/IPA/IPA_2images_blend/logo2.h
/GD32F4xx_Firmware_Library/GD32F4xx_Firmware_Library/Examples/IPA/IPA_image_copy/image_copy.h
/GD32F4xx_Firmware_Library/GD32F4xx_Firmware_Library/Examples/IPA/IPA_image_copy/logo.h
fix reason: 
Add 4-byte alignment(Fix the issue of running under high optimization level in EB)
V2.0.2:
NONE
V2.0.3:
#if defined(__GNUC__)
    __attribute__((aligned(4))) const unsigned char gImage_logo[73280] = { /* 0X00,0X10,0XE5,0X00,0XA0,0X00,0X01,0X1B, */
#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
    __align(4) const unsigned char gImage_logo[73280] = { /* 0X00,0X10,0XE5,0X00,0XA0,0X00,0X01,0X1B, */
#elif defined(__ICCARM__)
    #pragma data_alignment=4
    const unsigned char gImage_logo[73280] = { /* 0X00,0X10,0XE5,0X00,0XA0,0X00,0X01,0X1B, */
#else
    const unsigned char gImage_logo[73280] = { /* 0X00,0X10,0XE5,0X00,0XA0,0X00,0X01,0X1B, */
#endif
__________________________________________________________________________________________________________________________


__________________FMC________________________________________________________________________________________________
/GD32F4xx_Firmware_Library/GD32F4xx_Firmware_Library/Examples/FMC/Program_erase/fmc_operation.c

fix reason: 
Remove the Flash erase-related logic from the FMC example

V2.0.2:
void fmc_write_32bit_data(uint32_t address, uint16_t length, int32_t *data_32)
{
    fmc_sector_info_struct start_sector_info;
    fmc_sector_info_struct end_sector_info;
    uint32_t sector_num, i;

    printf("\r\nFMC word programe operation:\n");
    /* unlock the flash program erase controller */
    fmc_unlock();
    /* clear pending flags */
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
    /* get the information of the start and end sectors */
    start_sector_info = fmc_sector_info_get(address);
    end_sector_info = fmc_sector_info_get(address + 4 * length);
    /* erase sector */
    for(i = start_sector_info.sector_name; i <= end_sector_info.sector_name; i++) {
        sector_num = sector_name_to_number(i);
        if(FMC_READY != fmc_sector_erase(sector_num)) {
            while(1);
        }
    }

    /* write data_32 to the corresponding address */
    for(i = 0; i < length; i++) {
        if(FMC_READY == fmc_word_program(address, data_32[i])) {
            address = address + 4;
        } else {
            while(1);
        }
    }
    /* lock the flash program erase controller */
    fmc_lock();
    printf("\r\nWrite complete!\n");
    printf("\r\n");
}

/*!
    \brief      read 32 bit length data from a given address
    \param[in]  address: a given address(0x08000000~0x082FFFFF)
    \param[in]  length: data length
    \param[in]  data_32: data pointer
    \param[out] none
    \retval     none
*/
void fmc_read_32bit_data(uint32_t address, uint16_t length, int32_t *data_32)
{
    uint8_t i;
    printf("\r\nRead data from 0x%08X\n", address);
    printf("\r\n");
    for(i = 0; i < length; i++) {
        data_32[i] = *(__IO int32_t *)address;
        printf("0x%08X  ", data_32[i]);
        address = address + 4;
    }
    printf("\r\nRead end\n");
    printf("\r\n");
}

/*!
    \brief      write 16 bit length data to a given address
    \param[in]  address: a given address(0x08000000~0x082FFFFF)
    \param[in]  length: data length
    \param[in]  data_16: data pointer
    \param[out] none
    \retval     none
*/
void fmc_write_16bit_data(uint32_t address, uint16_t length, int16_t *data_16)
{
    fmc_sector_info_struct start_sector_info;
    fmc_sector_info_struct end_sector_info;
    uint32_t sector_num, i;

    printf("\r\nFMC half_word program operation:\n");
    /* unlock the flash program erase controller */
    fmc_unlock();
    /* clear pending flags */
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
    /* get the information of the start and end sectors */
    start_sector_info = fmc_sector_info_get(address);
    end_sector_info = fmc_sector_info_get(address + 2 * length);
    /* erase sector */
    for(i = start_sector_info.sector_name; i <= end_sector_info.sector_name; i++) {
        sector_num = sector_name_to_number(i);
        if(FMC_READY != fmc_sector_erase(sector_num)) {
            while(1);
        }
    }

    /* write data_16 to the corresponding address */
    for(i = 0; i < length; i++) {
        if(FMC_READY == fmc_halfword_program(address, data_16[i])) {
            address = address + 2;
        } else {
            while(1);
        }
    }
    /* lock the flash program erase controller */
    fmc_lock();
    printf("\r\nWrite complete!\n");
    printf("\r\n");
}

/*!
    \brief      read 16 bit length data to a given address
    \param[in]  address: a given address(0x08000000~0x082FFFFF)
    \param[in]  length: data length
    \param[in]  data_16: data pointer
    \param[out] none
    \retval     none
*/
void fmc_read_16bit_data(uint32_t address, uint16_t length, int16_t *data_16)
{
    uint8_t i;
    printf("\r\nRead data from 0x%04X\n", address);
    printf("\r\n");
    for(i = 0; i < length; i++) {
        data_16[i] = *(__IO int16_t *)address;
        printf("0x%04X  ", data_16[i]);
        address = address + 2;
    }
    printf("\r\nRead end\n");
    printf("\r\n");
}

/*!
    \brief      write 8 bit length data to a given address
    \param[in]  address: a given address(0x08000000~0x082FFFFF)
    \param[in]  length: data length
    \param[in]  data_8: data pointer
    \param[out] none
    \retval     none
*/
void fmc_write_8bit_data(uint32_t address, uint16_t length, int8_t *data_8)
{
    fmc_sector_info_struct start_sector_info;
    fmc_sector_info_struct end_sector_info;
    uint32_t sector_num, i;

    printf("\r\nFMC half_word program operation:\n");
    /* unlock the flash program erase controller */
    fmc_unlock();
    /* clear pending flags */
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
    /* get the information of the start and end sectors */
    start_sector_info = fmc_sector_info_get(address);
    end_sector_info = fmc_sector_info_get(address + 2 * length);
    /* erase sector */
    for(i = start_sector_info.sector_name; i <= end_sector_info.sector_name; i++) {
        sector_num = sector_name_to_number(i);
        if(FMC_READY != fmc_sector_erase(sector_num)) {
            while(1);
        }
    }

    /* write data_8 to the corresponding address */
    for(i = 0; i < length; i++) {
        if(FMC_READY == fmc_byte_program(address, data_8[i])) {
            address++;
        } else {
            while(1);
        }
    }
    /* lock the flash program erase controller */
    fmc_lock();
    printf("\r\nWrite complete!\n");
    printf("\r\n");
}

V2.0.3:
void fmc_write_32bit_data(uint32_t address, uint16_t length, int32_t *data_32)
{
    uint32_t i;

    printf("\r\nFMC word programe operation:\n");
    /* unlock the flash program erase controller */
    fmc_unlock();
    /* clear pending flags */
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);

    /* write data_32 to the corresponding address */
    for(i = 0; i < length; i++) {
        if(FMC_READY == fmc_word_program(address, data_32[i])) {
            address = address + 4;
        } else {
            while(1);
        }
    }
    /* lock the flash program erase controller */
    fmc_lock();
    printf("\r\nWrite complete!\n");
    printf("\r\n");
}

/*!
    \brief      read 32 bit length data from a given address
    \param[in]  address: a given address(0x08000000~0x082FFFFF)
    \param[in]  length: data length
    \param[in]  data_32: data pointer
    \param[out] none
    \retval     none
*/
void fmc_read_32bit_data(uint32_t address, uint16_t length, int32_t *data_32)
{
    uint8_t i;
    printf("\r\nRead data from 0x%08X\n", address);
    printf("\r\n");
    for(i = 0; i < length; i++) {
        data_32[i] = *(__IO int32_t *)address;
        printf("0x%08X  ", data_32[i]);
        address = address + 4;
    }
    printf("\r\nRead end\n");
    printf("\r\n");
}

/*!
    \brief      write 16 bit length data to a given address
    \param[in]  address: a given address(0x08000000~0x082FFFFF)
    \param[in]  length: data length
    \param[in]  data_16: data pointer
    \param[out] none
    \retval     none
*/
void fmc_write_16bit_data(uint32_t address, uint16_t length, int16_t *data_16)
{
    uint32_t i;

    printf("\r\nFMC half_word program operation:\n");
    /* unlock the flash program erase controller */
    fmc_unlock();
    /* clear pending flags */
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);

    /* write data_16 to the corresponding address */
    for(i = 0; i < length; i++) {
        if(FMC_READY == fmc_halfword_program(address, data_16[i])) {
            address = address + 2;
        } else {
            while(1);
        }
    }
    /* lock the flash program erase controller */
    fmc_lock();
    printf("\r\nWrite complete!\n");
    printf("\r\n");
}

/*!
    \brief      read 16 bit length data to a given address
    \param[in]  address: a given address(0x08000000~0x082FFFFF)
    \param[in]  length: data length
    \param[in]  data_16: data pointer
    \param[out] none
    \retval     none
*/
void fmc_read_16bit_data(uint32_t address, uint16_t length, int16_t *data_16)
{
    uint8_t i;
    printf("\r\nRead data from 0x%04X\n", address);
    printf("\r\n");
    for(i = 0; i < length; i++) {
        data_16[i] = *(__IO int16_t *)address;
        printf("0x%04X  ", data_16[i]);
        address = address + 2;
    }
    printf("\r\nRead end\n");
    printf("\r\n");
}

/*!
    \brief      write 8 bit length data to a given address
    \param[in]  address: a given address(0x08000000~0x082FFFFF)
    \param[in]  length: data length
    \param[in]  data_8: data pointer
    \param[out] none
    \retval     none
*/
void fmc_write_8bit_data(uint32_t address, uint16_t length, int8_t *data_8)
{
    uint32_t i;
    printf("\r\nFMC byte program operation:\n");
    /* unlock the flash program erase controller */
    fmc_unlock();
    /* clear pending flags */
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);

    /* write data_8 to the corresponding address */
    for(i = 0; i < length; i++) {
        if(FMC_READY == fmc_byte_program(address, data_8[i])) {
            address++;
        } else {
            while(1);
        }
    }
    /* lock the flash program erase controller */
    fmc_lock();
    printf("\r\nWrite complete!\n");
    printf("\r\n");
}

/GD32F4xx_Firmware_Library/GD32F4xx_Firmware_Library/Firmware/GD32F4xx_standard_peripheral/Source/gd32f4xx_fmc.c
fix reason:
Remove the Flash erase-related logic from the FMC example
V3.3.2:
/*!
    \brief    enable write protection
    \param[in]  ob_wp: specify sector to be write protected
                one or more parameters can be selected which are shown as below:
      \arg        OB_WP_x(x=0..22):sector x(x = 0,1,2...22)
      \arg        OB_WP_23_27: sector23~27
      \arg        OB_WP_ALL: all sector
    \param[out] none
    \retval     SUCCESS or ERROR
*/
ErrStatus ob_write_protection_enable(uint32_t ob_wp)
{
    uint32_t reg0 = FMC_OBCTL0;
    uint32_t reg1 = FMC_OBCTL1;
    fmc_state_enum fmc_state = FMC_READY;
    if(RESET != (FMC_OBCTL0 & FMC_OBCTL0_DRP)) {
        return ERROR;
    }
    /* wait for the FMC ready */
    fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);

    if(FMC_READY == fmc_state) {
        reg0 &= (~((uint32_t)ob_wp << 16U));
        reg1 &= (~(ob_wp & 0xFFFF0000U));
        FMC_OBCTL0 = reg0;
        FMC_OBCTL1 = reg1;

        return SUCCESS;
    } else {
        return ERROR;
    }
}

/*!
    \brief    disable write protection
    \param[in]  ob_wp: specify sector to be write protected
                one or more parameters can be selected which are shown as below:
      \arg        OB_WP_x(x=0..22):sector x(x = 0,1,2...22)
      \arg        OB_WP_23_27: sector23~27
      \arg        OB_WP_ALL: all sector
    \param[out] none
    \retval     SUCCESS or ERROR
*/
ErrStatus ob_write_protection_disable(uint32_t ob_wp)
{
    uint32_t reg0 = FMC_OBCTL0;
    uint32_t reg1 = FMC_OBCTL1;
    fmc_state_enum fmc_state = FMC_READY;
    if(RESET != (FMC_OBCTL0 & FMC_OBCTL0_DRP)) {
        return ERROR;
    }
    /* wait for the FMC ready */
    fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);

    if(FMC_READY == fmc_state) {
        reg0 |= ((uint32_t)ob_wp << 16U);
        reg1 |= (ob_wp & 0xFFFF0000U);
        FMC_OBCTL0 = reg0;
        FMC_OBCTL1 = reg1;

        return SUCCESS;
    } else {
        return ERROR;
    }
}

V3.3.3:
ErrStatus ob_write_protection_enable(uint32_t ob_wp)
{
    ErrStatus retval = SUCCESS;
    uint32_t reg0 = FMC_OBCTL0;
    uint32_t reg1 = FMC_OBCTL1;
    fmc_state_enum fmc_state = FMC_READY;
    if(RESET != (FMC_OBCTL0 & FMC_OBCTL0_DRP)) {
        retval = ERROR;
    } else {
        /* wait for the FMC ready */
        fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
        
        if(FMC_READY == fmc_state) {
            reg0 &= (~((uint32_t)ob_wp << 16U));
            reg1 &= (~(ob_wp & 0xFFFF0000U));
            FMC_OBCTL0 = reg0;
            FMC_OBCTL1 = reg1;
        
            retval = SUCCESS;
        } else {
            retval = ERROR;
        }
    }
    return retval;
}

/*!
    \brief    disable write protection
    \param[in]  ob_wp: specify sector to be write protected
                one or more parameters can be selected which are shown as below:
      \arg        OB_WP_x(x=0..22):sector x(x = 0,1,2...22)
      \arg        OB_WP_23_27: sector23~27
      \arg        OB_WP_ALL: all sector
    \param[out] none
    \retval     SUCCESS or ERROR
*/
ErrStatus ob_write_protection_disable(uint32_t ob_wp)
{
    ErrStatus retval = SUCCESS;
    uint32_t reg0 = FMC_OBCTL0;
    uint32_t reg1 = FMC_OBCTL1;
    fmc_state_enum fmc_state = FMC_READY;
    if(RESET != (FMC_OBCTL0 & FMC_OBCTL0_DRP)) {
        retval = ERROR;
    } else {
        /* wait for the FMC ready */
        fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
        
        if(FMC_READY == fmc_state) {
            reg0 |= ((uint32_t)ob_wp << 16U);
            reg1 |= (ob_wp & 0xFFFF0000U);
            FMC_OBCTL0 = reg0;
            FMC_OBCTL1 = reg1;
        
            retval = SUCCESS;
        } else {
            retval = ERROR;
        }
    }
    return retval;
}
__________________________________________________________________________________________________________________________

______________________RCU________________________________________________________________________________________________
/GD32A490_Firmware_Library/Firmware/CMSIS/GD/GD32A490/Source/system_gd32a490.c
fix reason: 
Add systeminit interrupt vector relocation
V2.0.2:
None
V2.0.3:
1.
#define VECT_TAB_OFFSET  (uint32_t)0x00             /* vector table base offset */
2.
#ifdef VECT_TAB_SRAM
    nvic_vector_table_set(NVIC_VECTTAB_RAM, VECT_TAB_OFFSET);
#else
    nvic_vector_table_set(NVIC_VECTTAB_FLASH, VECT_TAB_OFFSET);
#endif
__________________________________________________________________________________________________________________________

______________________ENET________________________________________________________________________________________________
/GD32A490_Firmware_Library/Examples/ENET/Telnet
fix reason: 
UPDATE lwip
V2.0.2:
/GD32A490_Firmware_Library/Examples/ENET/Telnet/lwip-2.1.2
V2.0.3:
/GD32A490_Firmware_Library/Examples/ENET/Telnet/lwip-2.2.1
__________________________________________________________________________________________________________________________

________________________Module PMU_______________________________________________________________________________________
/GD32A490_Firmware_Library/Examples/PMU/Deepsleep_wakeup_RTC/main.c
/GD32A490_Firmware_Library/Examples/PMU/Deepsleep_wakeup_exti/main.c
/GD32A490_Firmware_Library/Examples/PMU/Standby_wakeup_RTC/main.c
/GD32A490_Firmware_Library/Examples/PMU/Standby_wakeup_pin/main.c
fix reason: 
add switch frequence code to prevent vcore fluctuations
V2.0.2:
None
V2.0.3:
1.
/* software delay to prevent the impact of Vcore fluctuations.
   It is strongly recommended to include it to avoid issues caused by self-removal. */
static void _soft_delay_(uint32_t time)
{
    __IO uint32_t i;
    for(i=0; i<time*10; i++){
    }
}

2.
        /* The following is to prevent Vcore fluctuations caused by frequency switching. 
           It is strongly recommended to include it to avoid issues caused by self-removal. */
        rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV2);
        _soft_delay_(0x50);
        rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV4);
        _soft_delay_(0x50);
        rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV8);
        _soft_delay_(0x50);
        rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV16);
        _soft_delay_(0x50);
        rcu_system_clock_source_config(RCU_CKSYSSRC_IRC16M);
        _soft_delay_(200);
        rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV1);

__________________________________________________________________________________________________________________________

______________________SPI________________________________________________________________________________________________
/GD32A490_Firmware_Library/Firmware/GD32A490_standard_peripheral/Include/gd32a490_spi.h
/GD32A490_Firmware_Library/Firmware/GD32A490_standard_peripheral/Source/gd32a490_spi.c

fix reason: 
delete spi_quad_io23_output_disable()

V2.0.2:
1.
#define SPI_QCTL_IO23_DRV               BIT(2)                                  /*!< drive SPI_IO2 and SPI_IO3 enable */
2.
/*!
    \brief      enable SPI_IO2 and SPI_IO3 pin output
    \param[in]  spi_periph: SPIx(only x=5)
    \param[out] none
    \retval     none
*/
void spi_quad_io23_output_enable(uint32_t spi_periph)
{
    SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV;
}

/*!
   \brief      disable SPI_IO2 and SPI_IO3 pin output
   \param[in]  spi_periph: SPIx(only x=5)
   \param[out] none
   \retval     none
*/
void spi_quad_io23_output_disable(uint32_t spi_periph)
{
    SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV);
}

V2.0.3:
None

/GD32A490_Firmware_Library/Firmware/GD32A490_standard_peripheral/Include/gd32a490_spi.h
/GD32A490_Firmware_Library/Examples/SPI/I2S_master_slave_fullduplex_dma/main.c
fix reason: 
Correct spelling errors
V2.0.2:
PHILLIPS
V2.0.3:
PHILIPS
__________________________________________________________________________________________________________________________

______________________USB________________________________________________________________________________________________
/GD32A490_Firmware_Library/Examples/USB/USB_Device/dev_firmware_update/src/gd25qxx.c
fix reason: 
delete spi_quad_io23_output_disable()
V2.0.2:
    /* quad wire SPI_IO2 and SPI_IO3 pin output enable */
    spi_quad_io23_output_enable(SPI5);

V2.0.3:
None

Update and delete redundant FAT files
/GD32A490_Firmware_Library/Utilities/Third_Party/fat_fs/src/ff.c
v2.0.2:
1.
#include "integer.h"
#include "fattime.h"

V2.0.3:
1.
#include "ff.h"
#include "diskio.h"

2.
delete:
/GD32A490_Firmware_Library/Utilities/Third_Party/fat_fs/inc/fattime.h
/GD32A490_Firmware_Library/Utilities/Third_Party/fat_fs/inc/integer.h
/GD32A490_Firmware_Library/Utilities/Third_Party/fat_fs/readme.txt
/GD32A490_Firmware_Library/Utilities/Third_Party/fat_fs/src/option

/GD32A490_Firmware_Library/Firmware/GD32A490_usb_library/device/class/dfu/Source/dfu_core.c
fix reason: 
Fix the issue of PID acquisition failure
V2.0.2:
        .bLength         = USB_STRING_LEN(2U),
V2.0.3:
        .bLength         = USB_STRING_LEN(4U),
__________________________________________________________________________________________________________________________

______________________FWDGT________________________________________________________________________________________________
/GD32A490_Firmware_Library/Firmware/GD32A490_standard_peripheral/Source/gd32a490_fwdgt.c
fix reason: 
FWDGT must be enabled first, then write PSC and RLD, and wait until RUD and PUD are cleared.
V2.0.2:
/*!
    \brief      configure the free watchdog timer counter prescaler value
    \param[in]  prescaler_value: specify prescaler value
                only one parameter can be selected which is shown as below:
      \arg        FWDGT_PSC_DIV4: FWDGT prescaler set to 4
      \arg        FWDGT_PSC_DIV8: FWDGT prescaler set to 8
      \arg        FWDGT_PSC_DIV16: FWDGT prescaler set to 16
      \arg        FWDGT_PSC_DIV32: FWDGT prescaler set to 32
      \arg        FWDGT_PSC_DIV64: FWDGT prescaler set to 64
      \arg        FWDGT_PSC_DIV128: FWDGT prescaler set to 128
      \arg        FWDGT_PSC_DIV256: FWDGT prescaler set to 256
    \param[out] none
    \retval     ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value)
{
    uint32_t timeout = FWDGT_PSC_TIMEOUT;
    uint32_t flag_status = RESET;
  
    /* enable write access to FWDGT_PSC */
    FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
  
    /* wait until the PUD flag to be reset */
    do{
        flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
    }while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
    
    if ((uint32_t)RESET != flag_status){
        return ERROR;
    }
    
    /* configure FWDGT */
    FWDGT_PSC = (uint32_t)prescaler_value; 

    return SUCCESS;
}

/*!
    \brief      configure the free watchdog timer counter reload value
    \param[in]  reload_value: specify reload value(0x0000 - 0x0FFF)
    \param[out] none
    \retval     ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_reload_value_config(uint16_t reload_value)
{
    uint32_t timeout = FWDGT_RLD_TIMEOUT;
    uint32_t flag_status = RESET;
  
    /* enable write access to FWDGT_RLD */
    FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
  
    /* wait until the RUD flag to be reset */
    do{
        flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
    }while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
   
    if ((uint32_t)RESET != flag_status){
        return ERROR;
    }
    
    FWDGT_RLD = RLD_RLD(reload_value);

    return SUCCESS;
}

/*!
    \brief    reload the counter of FWDGT
    \param[in]  none
    \param[out] none
    \retval     none
*/
void fwdgt_counter_reload(void)
{
    FWDGT_CTL = FWDGT_KEY_RELOAD;
}

/*!
    \brief    configure counter reload value, and prescaler divider value
    \param[in]  reload_value: specify reload value(0x0000 - 0x0FFF)
    \param[in]  prescaler_div: FWDGT prescaler value
                only one parameter can be selected which is shown as below:
      \arg        FWDGT_PSC_DIV4: FWDGT prescaler set to 4
      \arg        FWDGT_PSC_DIV8: FWDGT prescaler set to 8
      \arg        FWDGT_PSC_DIV16: FWDGT prescaler set to 16
      \arg        FWDGT_PSC_DIV32: FWDGT prescaler set to 32
      \arg        FWDGT_PSC_DIV64: FWDGT prescaler set to 64
      \arg        FWDGT_PSC_DIV128: FWDGT prescaler set to 128
      \arg        FWDGT_PSC_DIV256: FWDGT prescaler set to 256
    \param[out] none
    \retval     ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div)
{
    uint32_t timeout = FWDGT_PSC_TIMEOUT;
    uint32_t flag_status = RESET;
  
    /* enable write access to FWDGT_PSC,and FWDGT_RLD */
    FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
  
    /* wait until the PUD flag to be reset */
    do{
       flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
    }while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
    
    if ((uint32_t)RESET != flag_status){
        return ERROR;
    }

    /* configure FWDGT */
    FWDGT_PSC = (uint32_t)prescaler_div;

    timeout = FWDGT_RLD_TIMEOUT;
    /* wait until the RUD flag to be reset */
    do{
       flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
    }while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
   
    if ((uint32_t)RESET != flag_status){
        return ERROR;
    }
    
    FWDGT_RLD = RLD_RLD(reload_value);
    
    /* reload the counter */
    FWDGT_CTL = FWDGT_KEY_RELOAD;

    return SUCCESS;
}

/*!
    \brief    get flag state of FWDGT
    \param[in]  flag: flag to get 
                only one parameter can be selected which is shown as below:
      \arg        FWDGT_STAT_PUD: a write operation to FWDGT_PSC register is on going
      \arg        FWDGT_STAT_RUD: a write operation to FWDGT_RLD register is on going
    \param[out] none
    \retval     FlagStatus: SET or RESET
*/
FlagStatus fwdgt_flag_get(uint16_t flag)
{
    if(RESET != (FWDGT_STAT & flag)){
        return SET;
  }

    return RESET;
}
V2.0.3:
/*!
    \brief      configure the free watchdog timer counter prescaler value
    \param[in]  prescaler_value: specify prescaler value
                only one parameter can be selected which is shown as below:
      \arg        FWDGT_PSC_DIV4: FWDGT prescaler set to 4
      \arg        FWDGT_PSC_DIV8: FWDGT prescaler set to 8
      \arg        FWDGT_PSC_DIV16: FWDGT prescaler set to 16
      \arg        FWDGT_PSC_DIV32: FWDGT prescaler set to 32
      \arg        FWDGT_PSC_DIV64: FWDGT prescaler set to 64
      \arg        FWDGT_PSC_DIV128: FWDGT prescaler set to 128
      \arg        FWDGT_PSC_DIV256: FWDGT prescaler set to 256
    \param[out] none
    \retval     ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value)
{
    uint32_t timeout = FWDGT_PSC_TIMEOUT;
    uint32_t flag_status;
    ErrStatus status = SUCCESS;

    /* enable write access to FWDGT_PSC */
    FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;

    /* configure FWDGT_PSC */
    FWDGT_PSC = (uint32_t)prescaler_value;

    /* wait until the PUD flag to be reset */
    do {
        flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
    } while((--timeout > 0U) && (0U != flag_status));

    if(0U != flag_status) {
        status = ERROR;
    }

    return status;
}

/*!
    \brief      configure the free watchdog timer counter reload value
    \param[in]  reload_value: specify reload value(0x0000 - 0x0FFF)
    \param[out] none
    \retval     ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_reload_value_config(uint16_t reload_value)
{
    uint32_t timeout = FWDGT_RLD_TIMEOUT;
    uint32_t flag_status;
    ErrStatus status = SUCCESS;

    /* enable write access to FWDGT_RLD */
    FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;

    /* configure FWDGT_RLD */
    FWDGT_RLD = RLD_RLD(reload_value);

    /* wait until the RUD flag to be reset */
    do {
        flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
    } while((--timeout > 0U) && (0U != flag_status));

    if(0U != flag_status) {
        status = ERROR;
    }

    return status;
}

/*!
    \brief    reload the counter of FWDGT
    \param[in]  none
    \param[out] none
    \retval     none
*/
void fwdgt_counter_reload(void)
{
    FWDGT_CTL = FWDGT_KEY_RELOAD;
}

/*!
    \brief    configure counter reload value, and prescaler divider value
    \param[in]  reload_value: specify reload value(0x0000 - 0x0FFF)
    \param[in]  prescaler_value: FWDGT prescaler value
                only one parameter can be selected which is shown as below:
      \arg        FWDGT_PSC_DIV4: FWDGT prescaler set to 4
      \arg        FWDGT_PSC_DIV8: FWDGT prescaler set to 8
      \arg        FWDGT_PSC_DIV16: FWDGT prescaler set to 16
      \arg        FWDGT_PSC_DIV32: FWDGT prescaler set to 32
      \arg        FWDGT_PSC_DIV64: FWDGT prescaler set to 64
      \arg        FWDGT_PSC_DIV128: FWDGT prescaler set to 128
      \arg        FWDGT_PSC_DIV256: FWDGT prescaler set to 256
    \param[out] none
    \retval     ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_value)
{
    uint32_t timeout = FWDGT_PSC_TIMEOUT;
    uint32_t flag_status;
    ErrStatus status = SUCCESS;

    /* start the free watchdog timer counter */
    FWDGT_CTL = FWDGT_KEY_ENABLE;

    /* enable write access to FWDGT_PSC,and FWDGT_RLD */
    FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;

    /* configure FWDGT_PSC */
    FWDGT_PSC = (uint32_t)prescaler_value;

    do {
        flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
    } while((--timeout > 0U) && (0U != flag_status));

    if(0U != flag_status) {
        status = ERROR;
    }

    if(SUCCESS == status) {
        /* configure FWDGT_RLD */
        FWDGT_RLD = RLD_RLD(reload_value);

        /* wait until the RUD flag to be reset */
        timeout = FWDGT_RLD_TIMEOUT;
        do {
            flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
        } while((--timeout > 0U) && (0U != flag_status));

        if(0U != flag_status) {
            status = ERROR;
        }
    }

    if(SUCCESS == status) {
        /* reload the counter */
        FWDGT_CTL = FWDGT_KEY_RELOAD;
    }

    return status;
}

/*!
    \brief    get flag state of FWDGT
    \param[in]  flag: flag to get
                only one parameter can be selected which is shown as below:
      \arg        FWDGT_STAT_PUD: a write operation to FWDGT_PSC register is on going
      \arg        FWDGT_STAT_RUD: a write operation to FWDGT_RLD register is on going
    \param[out] none
    \retval     FlagStatus: SET or RESET
*/
FlagStatus fwdgt_flag_get(uint16_t flag)
{
    FlagStatus flag_status = RESET;
    if(RESET != (FWDGT_STAT & flag)) {
        flag_status = SET;
    }
    return flag_status;
}

__________________________________________________________________________________________________________________________

______________________EXTI________________________________________________________________________________________________
/GD32A490_Firmware_Library/Firmware/GD32A490_standard_peripheral/Source/gd32a490_misc.c
fix reason: 
MODIFY nvic_irq_enable()
V2.0.2:
/*!
    \brief    enable NVIC request
    \param[in]  nvic_irq: the NVIC interrupt request, detailed in IRQn_Type
    \param[in]  nvic_irq_pre_priority: the pre-emption priority needed to set
    \param[in]  nvic_irq_sub_priority: the subpriority needed to set
    \param[out] none
    \retval     none
*/
void nvic_irq_enable(IRQn_Type nvic_irq, uint8_t nvic_irq_pre_priority,
                     uint8_t nvic_irq_sub_priority)
{
    uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U;
    /* use the priority group value to get the temp_pre and the temp_sub */
    if(((SCB->AIRCR) & (uint32_t)0x700U) == NVIC_PRIGROUP_PRE0_SUB4) {
        temp_pre = 0U;
        temp_sub = 0x4U;
    } else if(((SCB->AIRCR) & (uint32_t)0x700U) == NVIC_PRIGROUP_PRE1_SUB3) {
        temp_pre = 1U;
        temp_sub = 0x3U;
    } else if(((SCB->AIRCR) & (uint32_t)0x700U) == NVIC_PRIGROUP_PRE2_SUB2) {
        temp_pre = 2U;
        temp_sub = 0x2U;
    } else if(((SCB->AIRCR) & (uint32_t)0x700U) == NVIC_PRIGROUP_PRE3_SUB1) {
        temp_pre = 3U;
        temp_sub = 0x1U;
    } else if(((SCB->AIRCR) & (uint32_t)0x700U) == NVIC_PRIGROUP_PRE4_SUB0) {
        temp_pre = 4U;
        temp_sub = 0x0U;
    } else {
        nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
        temp_pre = 2U;
        temp_sub = 0x2U;
    }
    /* get the temp_priority to fill the NVIC->IP register */
    temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre);
    temp_priority |= nvic_irq_sub_priority & (0x0FU >> (0x4U - temp_sub));
    temp_priority = temp_priority << 0x04U;
    NVIC->IP[nvic_irq] = (uint8_t)temp_priority;
    /* enable the selected IRQ */
    NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU);
}

V2.0.3:
/*!
    \brief    enable NVIC request
    \param[in]  nvic_irq: the NVIC interrupt request, detailed in IRQn_Type
    \param[in]  nvic_irq_pre_priority: the pre-emption priority needed to set
    \param[in]  nvic_irq_sub_priority: the subpriority needed to set
    \param[out] none
    \retval     none
*/
void nvic_irq_enable(IRQn_Type nvic_irq, uint8_t nvic_irq_pre_priority,
                     uint8_t nvic_irq_sub_priority)
{
    uint32_t nvic_prigroup, nvic_priority;

    /* check current priority group */
    switch(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) {
    case NVIC_PRIGROUP_PRE0_SUB4:
    case NVIC_PRIGROUP_PRE1_SUB3:
    case NVIC_PRIGROUP_PRE2_SUB2:
    case NVIC_PRIGROUP_PRE3_SUB1:
    case NVIC_PRIGROUP_PRE4_SUB0:
        break;
    default:
        nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
        break;
    }

    /* get the priority group value */
    nvic_prigroup = NVIC_GetPriorityGrouping();

    /* encoding the pre-emption, subpriority priority */
    nvic_priority = NVIC_EncodePriority(nvic_prigroup, (uint32_t)nvic_irq_pre_priority, (uint32_t)nvic_irq_sub_priority);
    /* set priority */
    NVIC_SetPriority(nvic_irq, nvic_priority);

    /* enable the selected IRQ */
    NVIC_EnableIRQ(nvic_irq);
}
__________________________________________________________________________________________________________________________

______________________USART________________________________________________________________________________________________
/GD32A490_Firmware_Library/Examples/USART/IDLE_receive_interrupt/main.c
/GD32A490_Firmware_Library/Examples/USART/Receivertimeout/gd32a490_it.c
/GD32A490_Firmware_Library/Examples/USART/Receivertimeout/main.c
fix reason: 
add __IO
V2.0.2:
NONE 
V2.0.3:
__IO
__________________________________________________________________________________________________________________________

______________________CAN________________________________________________________________________________________________
/GD32A490_Firmware_Library/Firmware/GD32A490_standard_peripheral/Include/gd32a490_can.h
fix reason: 
Modification of CAN filter register base address (CAN filter 23 data 0 register / CAN filter 17 data 1 register)
V2.0.2:
1.#define CAN_F23DATA0(canx)                 REG32((canx) + 0x000003F8U)
2.#define CAN_F17DATA1(canx)                 REG32((canx) + 0x0000024CU)
V2.0.3:
1.#define CAN_F23DATA0(canx)                 REG32((canx) + 0x000002F8U)
2.#define CAN_F17DATA1(canx)                 REG32((canx) + 0x000002CCU) 

/GD32A490_Firmware_Library/Firmware/GD32A490_standard_peripheral/Source/gd32a490_can.c
fix reason: 
  Determine whether the CAN controller is transmitting with all three mailboxes simultaneously, 
and check if the mailbox to be aborted is the last one in the queue. If such an operation is attempted, 
the code should exit and notify the customer that the abort has failed.
V2.0.2:
/*!
    \brief      stop CAN transmission
    \param[in]  can_periph
      \arg        CANx(x=0,1)
    \param[in]  mailbox_number
                only one parameter can be selected which is shown as below:
      \arg        CAN_MAILBOXx(x=0,1,2)
    \param[out] none
    \retval     none
*/
ErrStatus can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number)
{
    ErrStatus reval = SUCCESS;
    /* timeout for CAN_TSTAT_MSTx bits */
    uint32_t timeout = CAN_TIMEOUT;

    if(CAN_MAILBOX0 == mailbox_number) {
        if((CAN_CTL_TFO == (CAN_CTL(can_periph) & CAN_CTL_TFO)) && (CAN_TSTAT_TMLS0 == \
            (CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS0 | CAN_ALL_MAILBOX_EMPTY)))){
            reval = ERROR;
        } else {
            CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0;
            while((CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)) && (0U != timeout)) {
                timeout--;
            }
            if(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){
                reval = ERROR;
            }
        }
    } else if(CAN_MAILBOX1 == mailbox_number) {
        if((CAN_CTL_TFO == (CAN_CTL(can_periph) & CAN_CTL_TFO)) && (CAN_TSTAT_TMLS1 == \
            (CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS1 | CAN_ALL_MAILBOX_EMPTY)))){
            reval = ERROR;
        }else{
            CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1;
            while((CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)) && (0U != timeout)) {
                timeout--;
            }
            if(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){
                reval = ERROR;
            }
        }
        
    } else if(CAN_MAILBOX2 == mailbox_number) {
        if((CAN_CTL_TFO == (CAN_CTL(can_periph) & CAN_CTL_TFO)) && (CAN_TSTAT_TMLS2 == \
            (CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS2 | CAN_ALL_MAILBOX_EMPTY)))){
            reval = ERROR;
        }else{
            CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2;
            while((CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)) && (0U != timeout)) {
                timeout--;
            }
            if(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){
                reval = ERROR;
            }
        }
    } else {
        /* illegal parameters */
    }

    return reval;
}
V2.0.3:
ErrStatus can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number)
{
    ErrStatus reval = SUCCESS;
    /* timeout for CAN_TSTAT_MSTx bits */
    uint32_t timeout = CAN_TIMEOUT;

    if(CAN_MAILBOX0 == mailbox_number) {
        if((CAN_CTL_TFO == (CAN_CTL(can_periph) & CAN_CTL_TFO)) && (CAN_TSTAT_TMLS0 == \
            (CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS0 | CAN_ALL_MAILBOX_EMPTY)))){
            reval = ERROR;
        } else {
            CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0;
            while((CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)) && (0U != timeout)) {
                timeout--;
            }
            if(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){
                reval = ERROR;
            }
        }
    } else if(CAN_MAILBOX1 == mailbox_number) {
        if((CAN_CTL_TFO == (CAN_CTL(can_periph) & CAN_CTL_TFO)) && (CAN_TSTAT_TMLS1 == \
            (CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS1 | CAN_ALL_MAILBOX_EMPTY)))){
            reval = ERROR;
        }else{
            CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1;
            while((CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)) && (0U != timeout)) {
                timeout--;
            }
            if(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){
                reval = ERROR;
            }
        }
        
    } else if(CAN_MAILBOX2 == mailbox_number) {
        if((CAN_CTL_TFO == (CAN_CTL(can_periph) & CAN_CTL_TFO)) && (CAN_TSTAT_TMLS2 == \
            (CAN_TSTAT(can_periph) & (CAN_TSTAT_TMLS2 | CAN_ALL_MAILBOX_EMPTY)))){
            reval = ERROR;
        }else{
            CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2;
            while((CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)) && (0U != timeout)) {
                timeout--;
            }
            if(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){
                reval = ERROR;
            }
        }
    } else {
        /* illegal parameters */
    }

    return reval;
}

/GD32A490_Firmware_Library/Firmware/GD32A490_standard_peripheral/Include/gd32a490_can.h
fix reason: 
Correct spelling errors
V2.0.2:
1.NONE
2.void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number);
3./*!
    \brief      get CAN error type
    \param[in]  can_periph
      \arg        CANx(x=0,1)
    \param[out] none
    \retval     can_error_enum
      \arg        CAN_ERROR_NONE: no error
      \arg        CAN_ERROR_FILL: fill error
      \arg        CAN_ERROR_FORMATE: format error
      \arg        CAN_ERROR_ACK: ACK error
      \arg        CAN_ERROR_BITRECESSIVE: bit recessive
      \arg        CAN_ERROR_BITDOMINANTER: bit dominant error
      \arg        CAN_ERROR_CRC: CRC error
      \arg        CAN_ERROR_SOFTWARECFG: software configure
4.
/* CAN errors */
typedef enum {
    CAN_ERROR_NONE = 0,                                                 /*!< no error */
    CAN_ERROR_FILL,                                                     /*!< fill error */
    CAN_ERROR_FORMATE,                                                  /*!< format error */
    CAN_ERROR_ACK,                                                      /*!< ACK error */
    CAN_ERROR_BITRECESSIVE,                                             /*!< bit recessive error */
    CAN_ERROR_BITDOMINANTER,                                            /*!< bit dominant error */
    CAN_ERROR_CRC,                                                      /*!< CRC error */
    CAN_ERROR_SOFTWARECFG,                                              /*!< software configure */
} can_error_enum;
V2.0.3:
1.
/* CAN maibox empty status mask */
#define CAN_ALL_MAILBOX_EMPTY              ((uint32_t)0x1C000000U)      /*!< CAN maibox empty status mask */
2.
ErrStatus can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number);
3.
/*!
    \brief      get CAN error type
    \param[in]  can_periph
      \arg        CANx(x=0,1)
    \param[out] none
    \retval     can_error_enum
      \arg        CAN_ERROR_NONE: no error
      \arg        CAN_ERROR_FILL: fill error
      \arg        CAN_ERROR_FORMAT: format error
      \arg        CAN_ERROR_ACK: ACK error
      \arg        CAN_ERROR_BITRECESSIVE: bit recessive
      \arg        CAN_ERROR_BITDOMINANT: bit dominant error
      \arg        CAN_ERROR_CRC: CRC error
      \arg        CAN_ERROR_SOFTWARECFG: software configure
4.
/* CAN errors */
typedef enum {
    CAN_ERROR_NONE = 0,                                                 /*!< no error */
    CAN_ERROR_FILL,                                                     /*!< fill error */
    CAN_ERROR_FORMAT,                                                   /*!< format error */
    CAN_ERROR_ACK,                                                      /*!< ACK error */
    CAN_ERROR_BITRECESSIVE,                                             /*!< bit recessive error */
    CAN_ERROR_BITDOMINANT,                                              /*!< bit dominant error */
    CAN_ERROR_CRC,                                                      /*!< CRC error */
    CAN_ERROR_SOFTWARECFG,                                              /*!< software configure */
} can_error_enum;

/GD32A490_Firmware_Library/Firmware/GD32A490_standard_peripheral/Include/gd32a490_can.h
fix reason: 
Correct spelling errors
V2.0.2:
} can_trasnmit_message_struct;
V2.0.3:
} can_transmit_message_struct;
__________________________________________________________________________________________________________________________

******************* V2.0.2 2025-08-08 ******************************************************************************************
______________________Common______________________________________________________________________________________________

______________________________________________________________________________________________________________________

________________________Module ADC _______________________________________________________________________________________

__________________________________________________________________________________________________________________________

______________________ADTIMER_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________BKP_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________BL0TIMER____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________BL1TIMER____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________CAN_________________________________________________________________________________________________
../Firmware/GD32A490_standard_peripheral/Source/gd32a490_can.c
fix reason:
When the number of bytes sent by CAN exceeds 8, the frame sent by CAN to the bus will have a problem.

V2.0.1:
uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct *transmit_message)
{
    uint8_t mailbox_number = CAN_MAILBOX0;

    /* select one empty mailbox */
    if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)) {
        mailbox_number = CAN_MAILBOX0;
    } else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)) {
        mailbox_number = CAN_MAILBOX1;
    } else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)) {
        mailbox_number = CAN_MAILBOX2;
    } else {
        mailbox_number = CAN_NOMAILBOX;
    }
    /* return no mailbox empty */
    if(CAN_NOMAILBOX == mailbox_number) {
        return CAN_NOMAILBOX;
    }

    CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN;
    if(CAN_FF_STANDARD == transmit_message->tx_ff) {
        /* set transmit mailbox standard identifier */
        CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \
                                               transmit_message->tx_ft);
    } else {
        /* set transmit mailbox extended identifier */
        CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \
                                               transmit_message->tx_ff | \
                                               transmit_message->tx_ft);
    }
    /* set the data length */
    CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_DLENC;
    CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen;
    /* set the data */
    CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \
            TMDATA0_DB2(transmit_message->tx_data[2]) | \
            TMDATA0_DB1(transmit_message->tx_data[1]) | \
            TMDATA0_DB0(transmit_message->tx_data[0]);
    CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \
            TMDATA1_DB6(transmit_message->tx_data[6]) | \
            TMDATA1_DB5(transmit_message->tx_data[5]) | \
            TMDATA1_DB4(transmit_message->tx_data[4]);
    /* enable transmission */
    CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN;

    return mailbox_number;
}

V2.0.2:
uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct *transmit_message)
{
    uint8_t mailbox_number = CAN_MAILBOX0;

    /* select one empty mailbox */
    if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)) {
        mailbox_number = CAN_MAILBOX0;
    } else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)) {
        mailbox_number = CAN_MAILBOX1;
    } else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)) {
        mailbox_number = CAN_MAILBOX2;
    } else {
        mailbox_number = CAN_NOMAILBOX;
    }
    /* return no mailbox empty */
    if(CAN_NOMAILBOX == mailbox_number) {
        return CAN_NOMAILBOX;
    }

    CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN;
    if(CAN_FF_STANDARD == transmit_message->tx_ff) {
        /* set transmit mailbox standard identifier */
        CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \
                                               transmit_message->tx_ft);
    } else {
        /* set transmit mailbox extended identifier */
        CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \
                                               transmit_message->tx_ff | \
                                               transmit_message->tx_ft);
    }
    /* set the data length */
    CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_DLENC;
    
    /* Classic CAN frame data lenth does not exceed 8 */
    if (transmit_message->tx_dlen > 8U) {
        transmit_message->tx_dlen = 8U;
    }
    
    CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen;
    /* set the data */
    CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \
            TMDATA0_DB2(transmit_message->tx_data[2]) | \
            TMDATA0_DB1(transmit_message->tx_data[1]) | \
            TMDATA0_DB0(transmit_message->tx_data[0]);
    CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \
            TMDATA1_DB6(transmit_message->tx_data[6]) | \
            TMDATA1_DB5(transmit_message->tx_data[5]) | \
            TMDATA1_DB4(transmit_message->tx_data[4]);
    /* enable transmission */
    CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN;

    return mailbox_number;
}

__________________________________________________________________________________________________________________________

______________________CAU_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________CEC_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________CFMU________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________CLA_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________CLTCFG______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________CMP_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________CPDM________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________CRC_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________CTC_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________DAC_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________DBG_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________DBGSYS______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________DCI_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________DCM_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________DMA_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________DMAMUX______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________EDOUT_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________EFUSE_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________ENET________________________________________________________________________________________________

_________________________________________________________________________________________________________________________

______________________EVIC________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________EXMC________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________EXTI________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________FAC_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________FFT_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________FMC_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________FMU_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________GPIO________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________GPTIMER_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________GTOC________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________GTOC________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________GPTIMER_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________GTOC________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HPDF________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_CAU_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_DMA_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_HAU_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_IF______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_PKCAU___________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_RCU_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_SM2_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_SM3_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_SM4_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_Timer___________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_TRNG____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HSM_WDGT____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________HWSEM_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________I2C_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________ICACHE______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________IFRP________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________IOC_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________IPA_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________IREF________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________IRM_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________IVREF_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________LIN_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________LPDTS_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________LPTIMER_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________LPUSART_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________MCMU________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________MDIO________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________MDMA________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________MFCOM_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________MTC_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________OPA_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________OSPI________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________OSPIM_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________PKCAU_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________PMU_________________________________________________________________________________________________
../Firmware/GD32A490_standard_peripheral/Source/gd32a490_pmu.c
fix reason:
Modifying the pmu_to_sleepmode() function to enter sleep with WFE requires one SEV instruction and two WFE instructions
V2.0.1:
void pmu_to_sleepmode(uint8_t sleepmodecmd)
{
    /* clear sleepdeep bit of Cortex-M4 system control register */
    SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);

    /* select WFI or WFE command to enter sleep mode */
    if(WFI_CMD == sleepmodecmd) {
        __WFI();
    } else {
        __WFE();
    }
V2.0.2:
void pmu_to_sleepmode(uint8_t sleepmodecmd)
{
    /* clear sleepdeep bit of Cortex-M4 system control register */
    SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);

    /* select WFI or WFE command to enter sleep mode */
    if(WFI_CMD == sleepmodecmd) {
        __WFI();
    } else {
        __SEV();
        __WFE();
        __WFE();
    }
}
_________________________________________________________________________________________________________________________

______________________POC_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________QSPI________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________RAMECCMU____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________RCU_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________RSPDIF______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________RTC_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________RTDEC_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________SAI_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________SDIO________________________________________________________________________________________________

_________________________________________________________________________________________________________________________

______________________SENT________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________SHRTIMER____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________SLCD________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________SPI_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________SQPI________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________STCM________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________SVPWM_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________SYSTEM______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________TIMER_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________TLI_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________TMU_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________TRIGSEL_____________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________TRNG________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________TSI_________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________TZPCU_______________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________USART_______________________________________________________________________________________________

________________________________________________________________________________________________________________________

______________________USBD________________________________________________________________________________________________
../Firmware/GD32A490_usb_library/device/core/Source/usbd_core.c
../Firmware/GD32A490_usb_library/device/core/Source/usbd_enum.c
fix reason:
CVTest testing through self-powered supply.
V2.0.1:
1.
static usb_reqsta _usb_std_getstatus(usb_core_driver *udev, usb_req *req)
{
    uint8_t recp = BYTE_LOW(req->wIndex);
    usb_reqsta req_status = REQ_NOTSUPP;
    usb_transc *transc = &udev->dev.transc_in[0];

    static uint8_t status[2] = {0U};

    switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) {
    case USB_RECPTYPE_DEV:
        if(((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \
                ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) {

            if(udev->dev.pm.power_mode) {
                status[0] = USB_STATUS_SELF_POWERED;
            } else {
                status[0] = 0U;
            }

            if(udev->dev.pm.dev_remote_wakeup) {
                status[0] |= USB_STATUS_REMOTE_WAKEUP;
            } else {
                status[0] = 0U;
            }

            req_status = REQ_SUPP;
        }
        break;

    case USB_RECPTYPE_ITF:
        if(((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) {
            req_status = REQ_SUPP;
        }
        break;

    case USB_RECPTYPE_EP:
        if((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) {
            if(0x80U == (recp & 0x80U)) {
                status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall;
            } else {
                status[0] = udev->dev.transc_out[recp].ep_stall;
            }

            req_status = REQ_SUPP;
        }
        break;

    default:
        break;
    }

    if(REQ_SUPP == req_status) {
        transc->xfer_buf = status;
        transc->remain_len = 2U;
    }

    return req_status;
}
2.
void usbd_init(usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core)
{
    udev->dev.desc = desc;

    /* class callbacks */
    udev->dev.class_core = class_core;

    /* create serial string */
    serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]);

    /* configure USB capabilities */
    (void)usb_basic_init(&udev->bp, &udev->regs, core);

    usb_globalint_disable(&udev->regs);

    /* initializes the USB core*/
    (void)usb_core_init(udev->bp, &udev->regs);

    /* set device disconnect */
    usbd_disconnect(udev);

#ifndef USE_OTG_MODE
    usb_curmode_set(&udev->regs, DEVICE_MODE);
#endif /* USE_OTG_MODE */

    /* initializes device mode */
    (void)usb_devcore_init(udev);

    usb_globalint_enable(&udev->regs);

    /* set device connect */
    usbd_connect(udev);

    udev->dev.cur_status = (uint8_t)USBD_DEFAULT;
}

1.
static usb_reqsta _usb_std_getstatus(usb_core_driver *udev, usb_req *req)
{
    uint8_t recp = BYTE_LOW(req->wIndex);
    usb_reqsta req_status = REQ_NOTSUPP;
    usb_transc *transc = &udev->dev.transc_in[0];

    static uint8_t status[2] = {0U};

    switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) {
    case USB_RECPTYPE_DEV:
        if(((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \
                ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) {

            if(udev->dev.pm.power_mode) {
                status[0] = USB_STATUS_SELF_POWERED;
            } else {
                status[0] = 0U;
            }

            if(udev->dev.pm.dev_remote_wakeup) {
                status[0] |= USB_STATUS_REMOTE_WAKEUP;
            }

            req_status = REQ_SUPP;
        }
        break;

    case USB_RECPTYPE_ITF:
        if(((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) {
            req_status = REQ_SUPP;
        }
        break;

    case USB_RECPTYPE_EP:
        if((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) {
            if(0x80U == (recp & 0x80U)) {
                status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall;
            } else {
                status[0] = udev->dev.transc_out[recp].ep_stall;
            }

            req_status = REQ_SUPP;
        }
        break;

    default:
        break;
    }

    if(REQ_SUPP == req_status) {
        transc->xfer_buf = status;
        transc->remain_len = 2U;
    }

    return req_status;
}

2.
void usbd_init(usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core)
{
    udev->dev.desc = desc;

    /* class callbacks */
    udev->dev.class_core = class_core;

    /* create serial string */
    serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]);

     /* configure power management */
    udev->dev.pm.power_mode = (udev->dev.desc->config_desc[7] & BIT(6)) >> 6;

    /* configure USB capabilities */
    (void)usb_basic_init(&udev->bp, &udev->regs, core);

    usb_globalint_disable(&udev->regs);

    /* initializes the USB core*/
    (void)usb_core_init(udev->bp, &udev->regs);

    /* set device disconnect */
    usbd_disconnect(udev);

#ifndef USE_OTG_MODE
    usb_curmode_set(&udev->regs, DEVICE_MODE);
#endif /* USE_OTG_MODE */

    /* initializes device mode */
    (void)usb_devcore_init(udev);

    usb_globalint_enable(&udev->regs);

    /* set device connect */
    usbd_connect(udev);

    udev->dev.cur_status = (uint8_t)USBD_DEFAULT;
}

../Firmware/GD32A490_usb_library/driver/Source/drv_usb_dev.c
fix reason:
Fix the issue where the enum_speed parameter may cause an array out-of-bounds error.
V2.0.1:
1.
usb_status usb_transc0_active(usb_core_driver *udev, usb_transc *transc)
{
    __IO uint32_t *reg_addr = NULL;

    uint8_t enum_speed = udev->regs.dr->DSTAT & DSTAT_ES;

    /* get the endpoint number */
    uint8_t ep_num = transc->ep_addr.num;

    if(ep_num) {
        /* not endpoint 0 */
        return USB_FAIL;
    }

    if(transc->ep_addr.dir) {
        reg_addr = &udev->regs.er_in[0]->DIEPCTL;
    } else {
        reg_addr = &udev->regs.er_out[0]->DOEPCTL;
    }

    /* endpoint 0 is activated after USB clock is enabled */
    *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM);

    /* set endpoint 0 maximum packet length */
    *reg_addr |= EP0_MAXLEN[enum_speed];

    /* activate endpoint */
    *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT;

    return USB_OK;
}

2.
usb_status usb_transc_active(usb_core_driver *udev, usb_transc *transc)
{
    __IO uint32_t *reg_addr = NULL;
    uint32_t epinten = 0U;
    uint8_t enum_speed = udev->regs.dr->DSTAT & DSTAT_ES;

    /* get the endpoint number */
    uint8_t ep_num = transc->ep_addr.num;

    /* enable endpoint interrupt number */
    if(transc->ep_addr.dir) {
        reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL;

        epinten = 1U << ep_num;
    } else {
        reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL;

        epinten = 1U << (16U + ep_num);
    }

    /* if the endpoint is not active, need change the endpoint control register */
    if(!(*reg_addr & DEPCTL_EPACT)) {
        *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM);

        /* set endpoint maximum packet length */
        if(0U == ep_num) {
            *reg_addr |= EP0_MAXLEN[enum_speed];
        } else {
            *reg_addr |= transc->max_len;
        }

        /* activate endpoint */
        *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT;
    }

#ifdef USB_HS_DEDICATED_EP1_ENABLED
    if((1U == ep_num) && (USB_CORE_ENUM_HS == udev->bp.core_enum)) {
        udev->regs.dr->DEP1INTEN |= epinten;
    } else
#endif /* USB_HS_DEDICATED_EP1_ENABLED */
    {
        /* enable the interrupts for this endpoint */
        udev->regs.dr->DAEPINTEN |= epinten;
    }

    return USB_OK;
}


V2.0.2:
1.
usb_status usb_transc0_active(usb_core_driver *udev, usb_transc *transc)
{
    __IO uint32_t *reg_addr = NULL;

    uint8_t enum_speed = ((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U);

    /* get the endpoint number */
    uint8_t ep_num = transc->ep_addr.num;

    if(ep_num) {
        /* not endpoint 0 */
        return USB_FAIL;
    }

    if(transc->ep_addr.dir) {
        reg_addr = &udev->regs.er_in[0]->DIEPCTL;
    } else {
        reg_addr = &udev->regs.er_out[0]->DOEPCTL;
    }

    /* endpoint 0 is activated after USB clock is enabled */
    *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM);

    /* set endpoint 0 maximum packet length */
    *reg_addr |= EP0_MAXLEN[enum_speed];

    /* activate endpoint */
    *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT;

    return USB_OK;
}
2.
usb_status usb_transc_active(usb_core_driver *udev, usb_transc *transc)
{
    __IO uint32_t *reg_addr = NULL;
    uint32_t epinten = 0U;
    uint8_t enum_speed = ((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U);

    /* get the endpoint number */
    uint8_t ep_num = transc->ep_addr.num;

    /* enable endpoint interrupt number */
    if(transc->ep_addr.dir) {
        reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL;

        epinten = 1U << ep_num;
    } else {
        reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL;

        epinten = 1U << (16U + ep_num);
    }

    /* if the endpoint is not active, need change the endpoint control register */
    if(!(*reg_addr & DEPCTL_EPACT)) {
        *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM);

        /* set endpoint maximum packet length */
        if(0U == ep_num) {
            *reg_addr |= EP0_MAXLEN[enum_speed];
        } else {
            *reg_addr |= transc->max_len;
        }

        /* activate endpoint */
        *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT;
    }

#ifdef USB_HS_DEDICATED_EP1_ENABLED
    if((1U == ep_num) && (USB_CORE_ENUM_HS == udev->bp.core_enum)) {
        udev->regs.dr->DEP1INTEN |= epinten;
    } else
#endif /* USB_HS_DEDICATED_EP1_ENABLED */
    {
        /* enable the interrupts for this endpoint */
        udev->regs.dr->DAEPINTEN |= epinten;
    }

    return USB_OK;
}

__________________________________________________________________________________________________________________________

_____________________USBFS________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________USBHS_______________________________________________________________________________________________
../Firmware/GD32A490_usb_library/driver/Source/drv_usbh_int.c
fix reason:
In the host file drv_usbh_int.c, the handling of the out channel causes usb_pp_halt to be executed twice. 
Remove the redundant usb_pp_halt function.
V2.0.1:
static uint32_t usbh_int_pipe_out(usb_core_driver *udev, uint32_t pp_num)
{
    usbh_host *uhost = udev->host.data;
    usb_pr *pp_reg = udev->regs.pr[pp_num];
    usb_pipe *pp = &udev->host.pipe[pp_num];
    uint32_t intr_pp = pp_reg->HCHINTF;
    intr_pp &= pp_reg->HCHINTEN;

    if(intr_pp & HCHINTF_ACK) {
        if(1U == udev->host.pipe[pp_num].do_ping) {
            udev->host.pipe[pp_num].do_ping = 0U;
            pp->err_count = 0U;
            usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_ACK, PIPE_NAK);
        }

        pp_reg->HCHINTF = HCHINTF_ACK;
    } else if(intr_pp & HCHINTF_STALL) {
        usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL);
    } else if(intr_pp & HCHINTF_DTER) {
        usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR);
        pp_reg->HCHINTF = HCHINTF_NAK;
    } else if(intr_pp & HCHINTF_REQOVR) {
        usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR);
    } else if(intr_pp & HCHINTF_TF) {
        pp->err_count = 0U;
        usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF);
    } else if(intr_pp & HCHINTF_NAK) {
        if(0U == udev->host.pipe[pp_num].do_ping) {
            if(1U == udev->host.pipe[pp_num].supp_ping) {
                udev->host.pipe[pp_num].do_ping = 1U;
            }
        }

        pp->err_count = 0U;
        if(USB_USE_FIFO == udev->bp.transfer_mode) {
            usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK);
        } else {
            pp_reg->HCHINTF = HCHINTF_NAK;
        }
        usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK);
    } else if(intr_pp & HCHINTF_USBER) {
        pp->err_count++;
        usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR);
    } else if(intr_pp & HCHINTF_NYET) {
        if(CTL_STATUS_OUT != uhost->control.ctl_state) {
            if(0U == udev->host.pipe[pp_num].do_ping) {
                if(1U == udev->host.pipe[pp_num].supp_ping) {
                    udev->host.pipe[pp_num].do_ping = 1U;
                }
            }

            usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET);
        } else {
            usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_XF);
        }

        pp->err_count = 0U;
    } else if(intr_pp & HCHINTF_CH) {
        udev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE;

        switch(pp->pp_status) {
        case PIPE_XF:
            pp->urb_state = URB_DONE;

            if((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) {
                pp->data_toggle_out ^= 1U;
            }
            break;

        case PIPE_NAK:
            pp->urb_state = URB_NOTREADY;
            break;
        case PIPE_NYET:
            pp->urb_state = URB_DONE;

            if((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) {
                pp->data_toggle_out ^= 1U;
            }
            break;

        case PIPE_STALL:
            pp->urb_state = URB_STALL;
            break;

        case PIPE_TRACERR:
            if(3U == pp->err_count) {
                pp->urb_state = URB_ERROR;
                pp->err_count = 0U;
            }
            break;

        case PIPE_IDLE:
        case PIPE_HALTED:
        case PIPE_BBERR:
        case PIPE_REQOVR:
        case PIPE_DTGERR:
        default:
            break;
        }

        pp_reg->HCHINTF = HCHINTF_CH;
    } else {
        /* no operation */
    }

    return 1U;
}
V2.0.2:
static uint32_t usbh_int_pipe_out(usb_core_driver *udev, uint32_t pp_num)
{
    usbh_host *uhost = udev->host.data;
    usb_pr *pp_reg = udev->regs.pr[pp_num];
    usb_pipe *pp = &udev->host.pipe[pp_num];
    uint32_t intr_pp = pp_reg->HCHINTF;
    intr_pp &= pp_reg->HCHINTEN;

    if(intr_pp & HCHINTF_ACK) {
        if(1U == udev->host.pipe[pp_num].do_ping) {
            udev->host.pipe[pp_num].do_ping = 0U;
            pp->err_count = 0U;
            usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_ACK, PIPE_NAK);
        }

        pp_reg->HCHINTF = HCHINTF_ACK;
    } else if(intr_pp & HCHINTF_STALL) {
        usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL);
    } else if(intr_pp & HCHINTF_DTER) {
        usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR);
        pp_reg->HCHINTF = HCHINTF_NAK;
    } else if(intr_pp & HCHINTF_REQOVR) {
        usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR);
    } else if(intr_pp & HCHINTF_TF) {
        pp->err_count = 0U;
        usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF);
    } else if(intr_pp & HCHINTF_NAK) {
        if(0U == udev->host.pipe[pp_num].do_ping) {
            if(1U == udev->host.pipe[pp_num].supp_ping) {
                udev->host.pipe[pp_num].do_ping = 1U;
            }
        }

        pp->err_count = 0U;
        if(USB_USE_FIFO == udev->bp.transfer_mode) {
            usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK);
        } else {
            pp_reg->HCHINTF = HCHINTF_NAK;
        }
    } else if(intr_pp & HCHINTF_USBER) {
        pp->err_count++;
        usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR);
    } else if(intr_pp & HCHINTF_NYET) {
        if(CTL_STATUS_OUT != uhost->control.ctl_state) {
            if(0U == udev->host.pipe[pp_num].do_ping) {
                if(1U == udev->host.pipe[pp_num].supp_ping) {
                    udev->host.pipe[pp_num].do_ping = 1U;
                }
            }

            usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET);
        } else {
            usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_XF);
        }

        pp->err_count = 0U;
    } else if(intr_pp & HCHINTF_CH) {
        udev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE;

        switch(pp->pp_status) {
        case PIPE_XF:
            pp->urb_state = URB_DONE;

            if((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) {
                pp->data_toggle_out ^= 1U;
            }
            break;

        case PIPE_NAK:
            pp->urb_state = URB_NOTREADY;
            break;
        case PIPE_NYET:
            pp->urb_state = URB_DONE;

            if((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) {
                pp->data_toggle_out ^= 1U;
            }
            break;

        case PIPE_STALL:
            pp->urb_state = URB_STALL;
            break;

        case PIPE_TRACERR:
            if(3U == pp->err_count) {
                pp->urb_state = URB_ERROR;
                pp->err_count = 0U;
            }
            break;

        case PIPE_IDLE:
        case PIPE_HALTED:
        case PIPE_BBERR:
        case PIPE_REQOVR:
        case PIPE_DTGERR:
        default:
            break;
        }

        pp_reg->HCHINTF = HCHINTF_CH;
    } else {
        /* no operation */
    }

    return 1U;
}
__________________________________________________________________________________________________________________________

______________________VREF________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________WDGT________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

______________________WIFI________________________________________________________________________________________________


__________________________________________________________________________________________________________________________

